﻿using System.Windows.Input;
using MugenMvvmToolkit.Annotations;
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces.ViewModels;
using MugenMvvmToolkit.Interfaces.Views;
using MugenMvvmToolkit.Models;
using MugenMvvmToolkit.Utils;
#if TASKSUPPORT
using System.Threading.Tasks;
#else
using MugenMvvmToolkit.Interfaces;
#endif

namespace MugenMvvmToolkit.ViewModels
{
    /// <summary>
    ///     Represents the base class for the view-model, which are displayed in the UI and has <see cref="IView" />.
    /// </summary>
    [BaseViewModel(Priority = 8)]
    public abstract class WorkspaceViewModel : ViewModelBase, IWorkspaceViewModel
    {
        #region Fields

        /// <summary>
        /// Gets the closeable view model facade.
        /// </summary>
        private readonly CloseableViewModelFacade _closeableViewModelFacade;
        private IView _view;
        private string _displayName;
        private bool _isSelected;

        #endregion

        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="WorkspaceViewModel" /> class.
        /// </summary>
        protected WorkspaceViewModel()
        {
            _closeableViewModelFacade = GlobalSettings.GetCloseableFacade(this, CanClose, OnClosing, OnClosed);
        }

        #endregion

        #region Implementation of interfaces

        /// <summary>
        ///     Gets or sets the display name for the current model.
        /// </summary>
        public virtual string DisplayName
        {
            get { return _displayName; }
            set
            {
                if (value == _displayName) return;
                _displayName = value;
                OnPropertyChanged("DisplayName");
            }
        }

        /// <summary>
        ///     Gets or sets the <see cref="IView" />.
        /// </summary>
        public IView View
        {
            get { return _view; }
            set
            {
                if (Equals(value, _view)) return;
                IView oldValue = _view;
                _view = value;
                OnViewChanged(oldValue, value);
                OnPropertyChanged("View");
            }
        }

        /// <summary>
        ///     Gets or sets the property that indicates that current model is selected.
        /// </summary>
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (value.Equals(_isSelected)) return;
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }

        /// <summary>
        ///     Gets or sets a command that attempts to remove this workspace from the user interface.
        /// </summary>
        public ICommand CloseCommand
        {
            get { return _closeableViewModelFacade.CloseCommand; }
            set { _closeableViewModelFacade.CloseCommand = value; }
        }

#if TASKSUPPORT
        /// <summary>
        ///     Tries to close view-model.
        /// </summary>
        /// <param name="parameter">The specified parameter, if any.</param>
        /// <returns>An instance of task with result.</returns>
        public Task<bool> Close(object parameter)
        {
            EnsureIsNotDisposed();
            return _closeableViewModelFacade.Close(parameter);
        }
#else
        /// <summary>
        ///     Tries to close view-model.
        /// </summary>
        /// <param name="parameter">The specified parameter, if any.</param>
        /// <returns>An instance of operation with result.</returns>
        public IOperationResult<bool> Close(object parameter)
        {
            EnsureIsNotDisposed();
            return _closeableViewModelFacade.Close(parameter);
        }
#endif

        /// <summary>
        ///     Called when <see cref="ICloseableViewModel" /> removing from the workspace.
        /// </summary>
        public event ViewModelClosingDelegate Closing
        {
            add { _closeableViewModelFacade.Closing += value; }
            remove { _closeableViewModelFacade.Closing -= value; }
        }

        /// <summary>
        ///     Called when <see cref="ICloseableViewModel" /> removed from the workspace.
        /// </summary>
        public event ViewModelClosedDelegate Closed
        {
            add { _closeableViewModelFacade.Closed += value; }
            remove { _closeableViewModelFacade.Closed -= value; }
        }

        #endregion

        #region Methods

        /// <summary>
        ///     Occurs when an <see cref="IView" /> for the current <see cref="WorkspaceViewModel" /> changed.
        /// </summary>
        /// <param name="oldView">
        ///     The old value of <see cref="IView" />.
        /// </param>
        /// <param name="newView">
        ///     The new value of <see cref="IView" />.
        /// </param>
        protected virtual void OnViewChanged(IView oldView, IView newView)
        {
        }

        /// <summary>
        ///     Determines whether the specified command <c>CloseCommand</c> can be execute.
        /// </summary>
        /// <param name="param">The specified command parameter.</param>
        /// <returns>
        ///     If <c>true</c> - can execute, otherwise <c>false</c>.
        /// </returns>
        protected virtual bool CanClose(object param)
        {
            return true;
        }

#if TASKSUPPORT
        /// <summary>
        ///     Occurs when view model closing.
        /// </summary>
        /// <returns>
        ///     If <c>true</c> - close, otherwise <c>false</c>.
        /// </returns>
        protected virtual Task<bool> OnClosing(object parameter)
        {
            return MvvmUtils.TrueTaskResult;
        }
#else
        /// <summary>
        ///     Occurs on closing current view model.
        /// </summary>
        /// <returns>
        ///     If <c>true</c> - close, otherwise <c>false</c>.
        /// </returns>
        protected virtual IOperationResult<bool> OnClosing(object parameter)
        {
            return MvvmUtils.TrueOperationResult;
        }
#endif

        /// <summary>
        ///     Occurs when <c>CloseCommand</c> executed.
        /// </summary>
        protected virtual void OnClosed(object parameter)
        {
        }

        #endregion

        #region Overrides of ViewModelBase

        /// <summary>
        ///     Occurs after the initialization of the current <see cref="ViewModelBase" />.
        /// </summary>
        internal override void OnInitializedInternal()
        {
            _closeableViewModelFacade.ThreadManager = ThreadManager;
            base.OnInitializedInternal();
        }

        /// <summary>
        ///     Occurs after current view model disposed, use for clear resource and event listeners(Internal only).
        /// </summary>
        internal override void OnDisposeInternal(bool disposing)
        {
            if (disposing)
                _closeableViewModelFacade.Dispose();
            base.OnDisposeInternal(disposing);
        }

        #endregion
    }
}